<template>
  <div>
    <input type="file" @change="getFile">
  </div>
</template>


<script>
import SparkMD5 from "spark-md5";
import axios from "axios";

export default {
  name: 'App',
  data() {
    return {
      upload_file:{
        fileMD5:'',
        fileSuffix:'',
      },
      chunkSize: 1024 * 1024 * 5,
      init_file_req:{
        md5:'',
        totalSlice: 0,
        isSlice: 0,
        originalFileName: '',
        fileSize: 0,
        sliceFileSize: 0
      },
      //设置重试次数
      retryTimes: 4,
    }
  },
  mounted() {
  },
  created() {
  },
  methods: {
    async uploadInitReq(file){
      this.init_file_req.md5 = this.upload_file.fileMD5;
      //告诉后端分片大小
      this.init_file_req.sliceFileSize = this.chunkSize;
      //判断文件是否大于20M，是否执行分片
      if (this.init_file_req.fileSize > this.init_file_req.sliceFileSize){
        //设置是否分片
        this.init_file_req.isSlice = 1;
        //计算分片数量
        this.init_file_req.totalSlice = Math.ceil(file.size / this.chunkSize);
      }
      const response = await axios({
        url: 'http://localhost:8080/init/fileData',
        method: 'POST',
        data: this.init_file_req,
      });
      //判断是否初始化成功
      if (response.data.code === '0000'){
        await this.uploadFile(file);
      }
    },
    async uploadMinFile(file,sliceIndex,totalIndex){
      const formData = new FormData();
      formData.append('file', file);
      formData.append('md5', this.upload_file.fileMD5);
      formData.append('fileSuffix', this.upload_file.fileSuffix);
      formData.append('isSlice', this.init_file_req.isSlice);
      formData.append('sliceIndex', sliceIndex);
      formData.append('totalIndex', totalIndex);
      const response = await axios({
        url: 'http://localhost:8080/upload/file',
        method: 'POST',
        data: formData,
        headers: {
          'Content-Type': 'multipart/form-data'
        },
      });
      console.log(response)
      if (response.data.code == '0000'){
        console.log('分片文件或整个文件上传成功')
        return {code: response.data.code ,data: response.data.data}
      }
      else if (response.data.code == 'U001'){
        return {code: response.data.code ,data: response.data.data}
      }

    },
    async uploadFile(file){
      console.log('上传的文件为：',file.name)
      if (file.size <= this.chunkSize) {
        // 如果文件大小小于等于20MB，直接上传整个文件
        await this.uploadMinFile(file, 0, 0);
      } else {
        // 遍历分片
        for (let i = 0; i < this.init_file_req.totalSlice; i++) {
          // 计算分片起始位置和结束位置
          let start = i * this.chunkSize;
          // 计算分片结束位置
          let end = Math.min(start + this.chunkSize, file.size);
          // 创建分片
          let chunk = file.slice(start, end);
          //打印上传进度
          console.log(`上传进度：${(i / this.init_file_req.totalSlice * 100).toFixed(2)}%`);
          //上传的分片的序号
          console.log(`上传分片序号：${i}`)
          // 上传分片
          var result = await this.uploadMinFile(chunk, i, this.init_file_req.totalSlice);
          // 如果上传失败，重试
          if (result.code === 'U001'){
            i = result.data;
            if (this.retryTimes > 0){
              if (i >= 1){
                i = i - 1;
              }else{
                i = 0;
              }
            }
            this.retryTimes--;
            if (this.retryTimes === 0){
              console.log('上传失败');
              return
            }
          }
        }
      }
      console.log('上传成功')
    },
    getFile(event){
      const file = event.target.files[0];
      if (!file) return;
      //获得文件的后缀
      this.upload_file.fileSuffix = file.name.split('.').pop();
      //获得文件名
      this.init_file_req.originalFileName = file.name;
      //获取文件的大小
      this.init_file_req.fileSize = file.size;
      //获取文件的md5,其计算的文件单次不能大于2G
      this.getUploadFileMD5(file).then((md5Hash) => {
        this.upload_file.fileMD5 = md5Hash;
        //发送文件上传初始化请求
        this.uploadInitReq(file);
      }).catch((error) => {
        console.error(error);
      });
    },
    //计算文件的md5hash值
    getUploadFileMD5(file){
      return new Promise((resolve, reject) => {
        const fileReader = new FileReader();
        // 当文件读取完成时调用
        fileReader.onload = () => {
          const arrayBuffer = fileReader.result;
          const md5Hash = SparkMD5.ArrayBuffer.hash(arrayBuffer);
          resolve(md5Hash); // 解析Promise，并返回MD5哈希值
        };
        // 当文件读取发生错误时调用
        fileReader.onerror = (error) => {
          reject(error); // 拒绝Promise，并传递错误信息
        };
        // 开始读取文件为ArrayBuffer
        fileReader.readAsArrayBuffer(file);
      });
    }
  }
}
</script>

<style scoped>

</style>
